/**
  ******************************************************************************
  * @file    User/user.c
  * @author  JUSHENG Application Team
  * @version V1.0.4
  * @date    12-14-2021
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2021 JUSHENG</center></h2>
  *
  *
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "include.h"
#include "user.h"
#include "tk_cfg.h"

/** @addtogroup Template_Project
  * @{
  */

static u32 ust_spi_rxbuf[256/4];
u8 ust_spibuf[5];
u8 ust_txdata[256];
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void uart_init(void)
{
    TYPE_LL_GPIO_INIT gpio_struct;
    TYPE_LL_UART_INIT     uart_cfg;

    memset(&gpio_struct,0x00,sizeof(gpio_struct));
    memset(&uart_cfg, 0x0, sizeof(uart_cfg));

    ll_gpio_pin_af_config(GPIOB, LL_GPIO_PIN_SOURCE_2, LL_GPIO_AF_0);
    gpio_struct.gpio_pin   = LL_GPIO_PIN_2;
    gpio_struct.gpio_mode  = LL_GPIO_MODE_AF;
    gpio_struct.gpio_pupd  = LL_GPIO_PUPD_UP;
    ll_gpio_init(GPIOB, &gpio_struct);

    uart_cfg.baudrate       = LL_UARTx_BAUDRATE_115200;    
    uart_cfg.bit_width_sel  = LL_UART_WORD_LENGTH_8B;
    uart_cfg.parity         = LL_UART_PARITY_NO;
    uart_cfg.stop_bit_sel   = LL_UART_STOP_1B;

    ll_uart_init(UART1, &uart_cfg);
    debug_select_interface_set(DEBUG_UART1);
    ll_uart_enable(UART1); 
}
/** 
  * @brief  UST SPI read
  * @param  p_spi: UST0 module pointer
  * @param  buf:  buf for save reading data
  * @param  num:  data num
  * @retval None
  */
void ust_spi_rx_data(UST_TypeDef *p_ust, u8 *buf, u32 num)
{
    while(num--)
    {
        ll_ust_spi_rx_byte(p_ust, buf++);
    }
}
/** 
  * @brief  UST SPI write
  * @param  p_spi: UST0 module pointer
  * @param  buf:  buf for save writting data
  * @param  num:  data num
  * @retval None
  */
void ust_spi_tx_data(UST_TypeDef *p_ust, u8 *buf, u32 num)
{
    while(num--)
    {
        ll_ust_spi_tx_byte(p_ust, *buf);
        buf++;
    }
}
/** 
  * @brief  UST SPI flash read
  * @param  p_spi: UST0 module pointer
  * @param  code: flash cmd code
  * @param  buf:  buf for save reading data
  * @param  num:  data num
  * @retval None
  */
void ust_spi_flash_read(UST_TypeDef *p_ust, u8 code, u8 *buf, u32 num)
{
    ll_ust_spi_cs_low(p_ust);
    ll_ust_spi_tx_byte(p_ust, code);
    delay_ms(1);
    ust_spi_rx_data(p_ust, buf, num);
    ll_ust_spi_cs_high(p_ust);
}
/** 
  * @brief  UST SPI flash write
  * @param  p_spi: UST0 module pointer
  * @param  code: flash cmd code
  * @param  buf:  buf for save writing data
  * @param  num:  data num
  * @retval None
  */
void ust_spi_flash_write(UST_TypeDef *p_ust, u8 code, u8 *buf, u32 num)
{
    ll_ust_spi_cs_low(p_ust);
    ll_ust_spi_tx_byte(p_ust, code);
    if(num)
    {
        ust_spi_tx_data(p_ust, buf, num);
    }
    ll_ust_spi_cs_high(p_ust);
}
/**
  * @brief  UST0 SPI flash 64K erase operation
  * @param  p_spi: SPI module pointer
  * @param  addr:  Block start address to be erased
  * @retval None
  */
void ust_spi_flash_64kb_erase(UST_TypeDef *p_ust, u32 addr)
{
    u8 spi_buf[3];
    
    /* write enable */
    ust_spi_flash_write(p_ust, 0x06, NULL, 0);

    spi_buf[0] = addr>>16;
    spi_buf[1] = addr>>8;
    spi_buf[2] = addr;
    ust_spi_flash_write(p_ust, 0xD8, spi_buf, 3);
    
    /* waiting for busy = 0 */
    do {
        ust_spi_flash_read(p_ust, 0x05, spi_buf, 1);
    } while(spi_buf[0] & BIT(0));

    /* write disable */
    ust_spi_flash_write(p_ust, 0x04, NULL, 0);
}
/**
  * @brief  ust0 spi flash reads a page(256bytes) of data
  * @param  p_spi: SPI module pointer
  * @param  addr:  The page start address to be read
  * @param  buf:   The buf that receives the data
  * @retval None
  */
void ust_spi_flash_read_page(UST_TypeDef *p_ust, u32 addr, u8 *buf)
{
    u8 spi_buf[4];

    ll_ust_spi_cs_low(p_ust);
    
    spi_buf[0] = 0x03;
    spi_buf[1] = addr>>16;
    spi_buf[2] = addr>>8;
    spi_buf[3] = addr;
    ust_spi_tx_data(p_ust, spi_buf, 4);

    ust_spi_rx_data(p_ust, buf, 256);

    ll_ust_spi_cs_high(p_ust);
}
/**
  * @brief  spi flash writes a page(256bytes) of data
  * @param  p_spi: SPI module pointer
  * @param  addr:  The page start address to be write
  * @param  buf:   The buf that receives the data
  * @retval None
  */
void ust_spi_flash_page_program(UST_TypeDef *p_ust, u32 addr, u8 *buf)
{
    u8 spi_buf[4];

    /* write enable */
    ust_spi_flash_write(p_ust, 0x06, NULL, 0);

    ll_ust_spi_cs_low(p_ust);
    spi_buf[0] = 0x02;
    spi_buf[1] = addr>>16;
    spi_buf[2] = addr>>8;
    spi_buf[3] = addr;
    ust_spi_tx_data(p_ust, spi_buf, 4);

    ust_spi_tx_data(p_ust, buf, 256);
    ll_ust_spi_cs_high(p_ust);
    
    /* waiting busy to 0 */
    do {
        ust_spi_flash_read(p_ust, 0x05, spi_buf, 1);
    } while(spi_buf[0] & BIT(0));

    /* write disable */
    ust_spi_flash_write(p_ust, 0x04, NULL, 0);
}
/**
  * @brief  UST SPI init
  * @param  None
  * @retval None
  */
void ust_spi_init(void)
{
    TYPE_LL_GPIO_INIT        gpio_init;
    TYPE_LL_UST_SPI_INIT     ust_init;

    memset(&gpio_init, 0x00, sizeof(gpio_init));
    memset(&ust_init, 0x00, sizeof(ust_init));
    memset(&ust_init, 0, sizeof(ust_init));

    ll_gpio_pin_af_config(GPIOA, LL_GPIO_PIN_SOURCE_0, LL_GPIO_AF_0);
    ll_gpio_pin_af_config(GPIOA, LL_GPIO_PIN_SOURCE_1, LL_GPIO_AF_0);
    ll_gpio_pin_af_config(GPIOA, LL_GPIO_PIN_SOURCE_2, LL_GPIO_AF_0);
    ll_gpio_pin_af_config(GPIOA, LL_GPIO_PIN_SOURCE_3, LL_GPIO_AF_0);

    gpio_init.gpio_mode = LL_GPIO_MODE_AF;
    gpio_init.gpio_pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1 | LL_GPIO_PIN_2 | LL_GPIO_PIN_3;
    gpio_init.gpio_speed_level = LL_GPIO_SPEED_LEVEL_1;
    gpio_init.gpio_pupd = LL_GPIO_PUPD_DOWN;
    ll_gpio_init(GPIOA, &gpio_init);

    ust_init.spi_cs = ENABLE;
    ust_init.spi_wire_mode = LL_UST_SPI_NORMAL_MODE;
    ust_init.spi_frequency = 4000;
    
    ll_ust_spi_init(UST0, &ust_init);
}
/**
  * @brief  UST SPI handle
  * @param  None
  * @retval None
  */
void ust_spi_handle(void)
{
    u8 *p_rx = (u8 *)ust_spi_rxbuf;
    u16 ust_spi_i;
    memset(ust_spibuf,0x00,sizeof(ust_spibuf));
    /* Read the manufacturer ID byte and two device ID bytes */
    ust_spi_flash_read(UST0, 0x9F, ust_spibuf, 3);
    printf("spi flash test read flash id:0x%2x%2x%2x\r\n", ust_spibuf[0], ust_spibuf[1], ust_spibuf[2]);
    for(u16 i=0;i<sizeof(ust_txdata);i++)
    {
        ust_txdata[i] = i;
    }
    
    ust_spi_flash_64kb_erase(UST0, 0x000000);
    /* Page read operation */
    ust_spi_flash_read_page(UST0, 0x000000, p_rx);
    /* Check data */
    for(ust_spi_i=0; ust_spi_i<sizeof(ust_spi_rxbuf); ust_spi_i++) {
        if(p_rx[ust_spi_i] != 0xFF) {
            printf("spi flash erase test fail\r\n");
            break;
        }
    }
    if(ust_spi_i == sizeof(ust_spi_rxbuf)) {
        printf("spi flash erase test ok\r\n");
    }
      /* Write page data */
    ust_spi_flash_page_program(UST0, 0x000000, ust_txdata);
    memset(ust_spi_rxbuf, 0x00, sizeof(ust_spi_rxbuf));
     /* Read page data */
    ust_spi_flash_read_page(UST0, 0x000000, p_rx);
    for(ust_spi_i=0; ust_spi_i<20; ust_spi_i++) {
        if(p_rx[ust_spi_i] != ust_txdata[ust_spi_i]) {
            printf("spi flash page program test fail:%d\r\n", ust_spi_i);
            break;
        }
    }
    if(ust_spi_i == sizeof(ust_spi_i)) {
        printf("spi flash page program & page read ok\r\n");
    }
}

/**
  * @}
  */

/*************************** (C) COPYRIGHT 2021 JUSHENG ***** END OF FILE *****/
